package com.bluesky.jwf.example1.forms;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

import com.bluesky.jwf.ComponentFactory;
import com.bluesky.jwf.ComponentFactory.ComponentType;
import com.bluesky.jwf.component.Button;
import com.bluesky.jwf.component.Component;
import com.bluesky.jwf.component.Label;
import com.bluesky.jwf.component.LongTextField;
import com.bluesky.jwf.component.event.AbstractEventHandler;
import com.bluesky.jwf.component.select.DropDownList;
import com.bluesky.jwf.component.select.TextConverter;
import com.bluesky.jwf.component.window.MainWindow;
import com.bluesky.my4gl.core.Class;
import com.bluesky.my4gl.core.interpreter.Interpreter;
import com.bluesky.my4gl.core.parser.java.Parser;
import com.bluesky.my4gl.global.ClassLibrary;
import com.bluesky.my4gl.global.GlobalSettings;

public class My4glPlaygroundWindow extends MainWindow {

	private class CodeSample implements Serializable {
		String name;
		String code;

		public CodeSample(String name, String code) {
			this.name = name;
			this.code = code;
		}
	}

	private List<CodeSample> samples;

	private DropDownList sampleList;
	private LongTextField codeFiled;
	private Button runBtn;
	private LongTextField outputLabel;

	public My4glPlaygroundWindow() {
		setTitle("My4gl Playground");

		samples = new ArrayList<CodeSample>();

		// load code from files

		samples.add(new CodeSample("hello world",
				getClassCode("com.bluesky.my4gl.example.HelloWorld3")));
		samples.add(new CodeSample("fibonacci",
				getClassCode("com.bluesky.my4gl.example.Fibonacci3")));

	}

	private String getClassCode(String className) {
		String resourceName = className.replaceAll("\\.", "/");
		resourceName = "/" + resourceName + ".4gl";

		InputStream is = ClassLibrary.class.getResourceAsStream(resourceName);

		try {
			Reader reader = new InputStreamReader(is, "utf-8");

			BufferedReader input = new BufferedReader(reader);

			String line = null;

			StringBuilder sb = new StringBuilder();

			while ((line = input.readLine()) != null) {
				sb.append(line + "\r\n");

			}

			return sb.toString();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	@Override
	public void init(String html) {

		super.init(html);

		ComponentFactory factory = ComponentFactory.getInstance();

		sampleList = (DropDownList) factory
				.createComponent(ComponentType.DropDownList);
		bodyTag.loadByJwfClass("sampleList").replace(sampleList);
		sampleList.setTextConverter(new TextConverter() {
			@Override
			public String toText(Object obj) {
				CodeSample cs = (CodeSample) obj;
				return cs.name;
			}
		});
		sampleList.setItems(samples);

		sampleList.setChangeHandler(new AbstractEventHandler() {
			@Override
			public void handle(Component target, Object parameter) {

				DropDownList dl = (DropDownList) target;
				CodeSample cs = (CodeSample) dl.getSelectedItem();
				getCodeFiled().setText(cs.code);
			}
		});

		codeFiled = (LongTextField) factory.createComponent("LongTextField",
				bodyTag.loadByJwfClass("code").toHtml());
		bodyTag.loadByJwfClass("code").replace(codeFiled);

		runBtn = (Button) factory.createComponent(ComponentType.Button);
		bodyTag.loadByJwfClass("run").replace(runBtn);
		runBtn.setText("Compile & Run");

		outputLabel = (LongTextField) factory.createComponent(
				ComponentType.LongTextField.name(), bodyTag.loadByJwfClass(
						"output").toHtml());
		bodyTag.loadByJwfClass("output").replace(outputLabel);

		runBtn.setClickHandler(new AbstractEventHandler() {
			@Override
			public void handle(Component target, Object parameter) {

				try {

					Interpreter interpreter = new Interpreter();

					Parser parser = new Parser();
					InputStream is = new ByteArrayInputStream(codeFiled
							.getText().getBytes(
									GlobalSettings.getDefaultEncoding()));

					com.bluesky.my4gl.core.Class cls = parser.parseAndCompile(
							is, GlobalSettings.getDefaultEncoding());

					ClassLibrary.register(cls);

					ByteArrayOutputStream baos = new ByteArrayOutputStream();

					GlobalSettings.setStandardOutputStream(baos);

					interpreter.run(cls.getFullName(), "main", new String[] {});

					// baos.writeTo(System.out);
					String outputStr = baos.toString(GlobalSettings
							.getDefaultEncoding());
					getOutputLabel().setText(outputStr);

				} catch (Exception e) {
					getOutputLabel()
							.setText("error:" + e.getLocalizedMessage());

				}
			}
		});

		sampleList.setSelectedIndex(0);
	}

	public DropDownList getSampleList() {
		return sampleList;
	}

	public void setSampleList(DropDownList sampleList) {
		this.sampleList = sampleList;
	}

	public LongTextField getCodeFiled() {
		return codeFiled;
	}

	public void setCodeFiled(LongTextField codeFiled) {
		this.codeFiled = codeFiled;
	}

	public Button getRunBtn() {
		return runBtn;
	}

	public void setRunBtn(Button runBtn) {
		this.runBtn = runBtn;
	}

	public LongTextField getOutputLabel() {
		return outputLabel;
	}

	public void setOutputLabel(LongTextField outputLabel) {
		this.outputLabel = outputLabel;
	}

}
